package com.hyt.it.ogt.kq.service.gov.examsystem.implement;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.hyt.core.util.StringUtils;
import com.hyt.it.ogt.kq.common.config.ConfigManager;
import com.hyt.it.ogt.kq.common.gov.config.HuaweiCloudObsConfig;
import com.hyt.it.ogt.kq.common.gov.config.ObtConfig;
import com.hyt.it.ogt.kq.common.gov.constant.CodeEnum;
import com.hyt.it.ogt.kq.common.gov.constant.ResponseCode;
import com.hyt.it.ogt.kq.common.gov.constant.examsys.ActionEnum;
import com.hyt.it.ogt.kq.common.gov.constant.examsys.obt.OBTParamEnum;
import com.hyt.it.ogt.kq.common.gov.constant.examsys.obt.OBTResultEnum;
import com.hyt.it.ogt.kq.common.gov.constant.examsys.obt.OBTStateTypeEnum;
import com.hyt.it.ogt.kq.service.gov.examsystem.ExamSystem;
import com.hyt.it.ogt.kq.common.config.exception.KqException;
import com.hyt.it.ogt.kq.service.gov.model.dto.*;
import com.hyt.it.ogt.kq.service.gov.model.entity.*;
import com.hyt.it.ogt.kq.service.gov.model.json.examsys.HuaweiCloudObsInfo;
import com.hyt.it.ogt.kq.service.gov.model.json.examsys.obt.OumaExaminationConfig;
import com.hyt.it.ogt.kq.service.gov.model.json.examsys.obt.PlaceTimeResult;
import com.hyt.it.ogt.kq.service.gov.model.json.examsys.obt.RoomInfoResult;
import com.hyt.it.ogt.kq.service.gov.model.json.examsys.obt.TimeInfoResult;
import com.hyt.it.ogt.kq.service.gov.model.param.OumaParam;
import com.hyt.it.ogt.kq.service.gov.model.xml.examsys.obt.*;
import com.hyt.it.ogt.kq.service.gov.photo.PhotoTypeEnum;
import com.hyt.it.ogt.kq.common.gov.secmodule.SecModuleUtil;
import com.hyt.it.ogt.kq.service.gov.service.*;
import com.hyt.it.ogt.kq.common.gov.utils.DateTimeUtil;
import com.hyt.it.ogt.kq.common.gov.utils.HuaweiCloudObsUtil;
import com.hyt.it.ogt.kq.common.gov.utils.XmlUtil;
import com.hyt.it.ogt.kq.service.model.entity.Subject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.time.Duration;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * OBT考试系统接口实现
 * </p>
 *
 * @author huangyh
 * @since 2021-07-19
 */
@Slf4j
@Component
public class ObtImplement implements ExamSystem {

    @Resource
    private IRegisterInfoService iRegisterInfoService;

    @Resource
    private ITaskRoomService iTaskRoomService;

    @Resource
    private ITaskService iTaskService;

    @Resource
    private ITimeService iTimeService;

    @Resource
    private ITimeRoomService iTimeRoomService;

    @Resource
    private ICandidateService iCandidateService;

    @Resource
    private IExamMonitorService iExamMonitorService;

    @Resource
    private IPaperService iPaperService;

    @Resource
    private IExamResultMonitorService iExamResultMonitorService;

    @Resource
    private ITaskPlaceService iTaskPlaceService;

    @Resource
    private ITaskConfigService iTaskConfigService;

    @Resource
    private ITaskRoomTestReportService iTaskRoomTestReportService;

    @Resource
    private ITaskRoomTestReportDetailService iTaskRoomTestReportDetailService;

    @Resource
    private ISysFileService iSysFileService;

    @Resource
    private ObtConfig obtConfig;

    @Resource
    private ConfigManager configManager;

    @Resource
    private HuaweiCloudObsConfig huaweiCloudObsConfig;

    @Override
    public String getRegisterInfo(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        //获取请求参数
        String code = request.getParameter(OBTParamEnum.GET_REGISTER_INFO_CODE.getParam());
        //获取考场注册信息
        RegisterInfoObtResult registerInfoObtResult = iTaskRoomService.getObtRegisterRoomInfo(taskCode, code);
        if (ObjectUtils.isEmpty(registerInfoObtResult)) {
            //未找到考场信息
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "未找到考场信息");
            registerInfoObtResult = new RegisterInfoObtResult();
            registerInfoObtResult.setFlag(OBTResultEnum.GET_REGISTER_INFO_NOT_FOUND.getResult());
            throw new KqException(ResponseCode.EXAMINATION_EXAM_SYSTEM_BUSINESS_EXCEPTION.getCode(),
                    XmlUtil.toXml(registerInfoObtResult));
        }
        //找到考场信息
        registerInfoObtResult.setFlag(OBTResultEnum.GET_REGISTER_INFO_FOUND.getResult());
        return XmlUtil.toXml(registerInfoObtResult);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String registerRoom(HttpServletRequest request, HttpServletResponse response, String taskCode) throws Exception {
        //获取请求参数
        String roomCode = request.getParameter(OBTParamEnum.REGISTER_ROOM_ROOM_CODE.getParam());
        //根据考试任务编号获取考场注册信息
        TaskRoom taskRoom = iTaskRoomService.getByTaskCodeAndCode(taskCode, roomCode);
        //校验考场注册信息是否为空
        if (ObjectUtils.isEmpty(taskRoom)) {
            //未找到相应考场，注册失败
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "未找到相应考场，注册失败");
            throw new KqException(OBTResultEnum.REGISTER_ROOM_NOT_FOUND.getResult(),
                    OBTResultEnum.REGISTER_ROOM_NOT_FOUND.getRemark());
        }
        //保存考场注册信息
        if (!this.saveRegisterInfo(taskRoom.getId(), request)) {
            //插入或更新注册信息表失败
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "插入或更新注册信息表失败");
            throw new KqException(OBTResultEnum.REGISTER_ROOM_EXCEPTION.getResult(),
                    OBTResultEnum.REGISTER_ROOM_EXCEPTION.getRemark());
        }
        //更新考场注册状态
        taskRoom.setRegistered(true);
        if (!iTaskRoomService.updateById(taskRoom)) {
            //更新任务考场表失败
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "更新任务考场表失败");
            throw new KqException(OBTResultEnum.REGISTER_ROOM_EXCEPTION.getResult(),
                    OBTResultEnum.REGISTER_ROOM_EXCEPTION.getRemark());
        }
        //考场注册成功
        return String.valueOf(OBTResultEnum.REGISTER_ROOM_SUCCESS.getResult());
    }

    /**
     * 保存考场注册信息
     * @param roomId 任务考场id
     * @param request 考试系统请求参数
     */
    private boolean saveRegisterInfo(String roomId, HttpServletRequest request) throws Exception {
        //获取考场注册信息
        RegisterInfo registerInfo = iRegisterInfoService.getByRoomId(roomId);
        RegisterInfo newRegisterInfo = new RegisterInfo();
        newRegisterInfo.setRoomId(roomId)
                .setLinkman(URLDecoder.decode(request.getParameter(OBTParamEnum.REGISTER_ROOM_LINK_MAN.getParam()), "UTF-8"))
                .setTelephone(request.getParameter(OBTParamEnum.REGISTER_ROOM_TEL.getParam()))
                .setIp(request.getParameter(OBTParamEnum.REGISTER_ROOM_IP_ADDRESS.getParam()))
                .setMac(request.getParameter(OBTParamEnum.REGISTER_ROOM_MAC.getParam()))
                .setCpuDiskCode(request.getParameter(OBTParamEnum.REGISTER_ROOM_CPU_AND_DISK_NO.getParam()))
                .setServerName(URLDecoder.decode(request.getParameter(OBTParamEnum.REGISTER_ROOM_SERVER_NAME.getParam()), "UTF-8"));
        if (ObjectUtils.isEmpty(registerInfo)) {
            //当前没有注册信息，插入注册信息
            return iRegisterInfoService.add(newRegisterInfo);
        }
        //当前存在注册信息，更新注册信息
        newRegisterInfo.setId(registerInfo.getId())
                .setCreateDate(registerInfo.getCreateDate())
                .setCreateBy(registerInfo.getCreateBy());
        return iRegisterInfoService.updateById(newRegisterInfo);
    }

    @Override
    public String getExamTaskList(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        ExamTaskObtResult examTaskObtResult = new ExamTaskObtResult();
        //获取考试任务信息
        Task task = iTaskService.getTaskByCode(taskCode);
        if (ObjectUtils.isEmpty(task)) {
            //考试任务已不存在，获取失败
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "考试任务已不存在，获取失败");
            examTaskObtResult.setFlag(OBTResultEnum.GET_EXAM_TASK_LIST_FAILED.getResult());
            throw new KqException(ResponseCode.EXAMINATION_EXAM_SYSTEM_BUSINESS_EXCEPTION.getCode(),
                    XmlUtil.toXml(examTaskObtResult));
        }
        //: 获取考试任务对应的考试系统版本号(后续需要优化为从缓存中获取)
        String examSystemVersion = iTaskConfigService.getExamSystemVersionByTaskCode(taskCode);
        //组装返回结果数据
        ExamTaskInfoObtResult info = new ExamTaskInfoObtResult();
        info.setName(task.getName()).setCode(task.getCode())
                .setYear(String.valueOf(task.getBeginDate().getYear()))
                .setMonth(String.valueOf(task.getBeginDate().getMonthValue()))
                .setMainUrl(configManager.getExaminationUrl() + taskCode)
                .setBackUrl(configManager.getExaminationUrl() + taskCode)
                .setExamSystemVersion(examSystemVersion);
        List<ExamTaskInfoObtResult> examTaskInfoObtResultList = new ArrayList<>();
        examTaskInfoObtResultList.add(info);
        examTaskObtResult.setItemList(examTaskInfoObtResultList)
                .setDatetime(String.valueOf(DateTimeUtil.date2double(Calendar.getInstance().getTime())))
                .setExaminationType(String.valueOf(CodeEnum.OBT_EXAMINATION_TYPE.getCode()))
                .setFlag(OBTResultEnum.GET_EXAM_TASK_LIST_SUCCESS.getResult());
        return XmlUtil.toXml(examTaskObtResult);
    }

    @Override
    public String getRoomPackage(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        //成功返回数据示例（不含双引号，多个批次用“|”分割）：“0#考试时间场次id#考试场次名称#考试场次开考时间#考试时长#考试科目名称#考场考务场次数据包状态#包的MD5值#包的下载地址”
        //OBT模拟测试考务数据由其本身生成，不需要考务提供模拟测试考务数据
        String roomCode = request.getParameter(OBTParamEnum.GET_ROOM_PACKAGE_ROOM_CODE.getParam());
        //获取考务包信息
        List<RoomDataPackageDTO> roomDataPackageDTOList = iTimeRoomService.getRoomDataPackageDTOList(taskCode, roomCode);
        //判断是否存在考务包
        if (CollectionUtils.isEmpty(roomDataPackageDTOList)) {
            //未有考务包
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "未有考务包");
            throw new KqException(OBTResultEnum.GET_ROOM_PACKAGE_WITHOUT.getResult(),
                    OBTResultEnum.GET_ROOM_PACKAGE_WITHOUT.getRemark());
        }
        //生成考务包信息文本
        StringBuffer result = new StringBuffer();
        result.append(OBTResultEnum.GET_ROOM_PACKAGE_SUCCESS.getResult())
                .append(ActionEnum.POUND_SIGN.getName());
        roomDataPackageDTOList.forEach(roomDataPackageDTO -> {
            //计算考试时间
            Duration duration = Duration.between(roomDataPackageDTO.getStartTime(),
                    roomDataPackageDTO.getEndTime());
            long examTime = duration.toMinutes();
            //组装科目名称
            String subjectNames = roomDataPackageDTO.getSubjectList().stream()
                    .map(Subject::getName)
                    .collect(Collectors.joining(","));
            //考试时间场次id
            result.append(roomDataPackageDTO.getCode())
                    .append(ActionEnum.POUND_SIGN.getName())
                    //考试场次名称
                    .append(roomDataPackageDTO.getName())
                    .append(ActionEnum.POUND_SIGN.getName())
                    //考试场次开考时间
                    .append(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                            .format(roomDataPackageDTO.getStartTime()))
                    .append(ActionEnum.POUND_SIGN.getName())
                    //考试时长
                    .append(examTime)
                    .append(ActionEnum.POUND_SIGN.getName())
                    //考试科目名称
                    .append(subjectNames)
                    .append(ActionEnum.POUND_SIGN.getName())
                    //数据包状态
                    .append(OBTResultEnum.ROOM_PACKAGE_USABLE.getResult())
                    .append(ActionEnum.POUND_SIGN.getName())
                    //MD5
                    .append(roomDataPackageDTO.getRoomDataMd5())
                    .append(ActionEnum.POUND_SIGN.getName())
                    //路径
                    .append(roomDataPackageDTO.getRoomDataPath())
                    .append(ActionEnum.VERTICAL_SIGN.getName());
        });
        //去除最后一个分隔符
        result.deleteCharAt(result.length() - 1);
        return result.toString();
    }

    @Override
    public String updateRoomPackageState(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        //暂无考务包下载管理表，直接返回成功状态
        return String.valueOf(OBTResultEnum.UPDATE_ROOM_PACKAGE_STATE_SUCCESS.getResult());
    }

    @Override
    public String getPaperData(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        //获取请求参数
        String dataType = request.getParameter(OBTParamEnum.GET_PAPER_DATA_TYPE.getParam());
        String roomCode = request.getParameter(OBTParamEnum.GET_PAPER_DATA_ROOM_CODE.getParam());
        String timeCode = request.getParameter(OBTParamEnum.GET_PAPER_DATA_TIME_CODE.getParam());
        StringBuffer result = new StringBuffer();
        if (OBTParamEnum.GET_PAPER_DATA_TYPE_FORMAL.getParam().equals(dataType)) {
            //正式试卷包
            //获取批次试卷信息
            List<PaperFileDTO> paperList = iPaperService.getForExamSystem(taskCode, roomCode, timeCode,
                    CodeEnum.FORMAL_PAPER.getCode());
            if (CollectionUtils.isEmpty(paperList)) {
                //未有试卷包，获取失败
                log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}",
                        OBTResultEnum.GET_PAPER_DATA_WITHOUT.getRemark());
                throw new KqException(OBTResultEnum.GET_PAPER_DATA_WITHOUT.getResult(),
                        OBTResultEnum.GET_PAPER_DATA_WITHOUT.getRemark());
            }
            //组装试卷信息返回数据
            result.append(OBTResultEnum.GET_PAPER_DATA_SUCCESS.getResult())
                    .append(ActionEnum.VERTICAL_SIGN.getName());
            paperList.forEach(paper -> {
                //试卷MD5
                result.append(paper.getMd5().toLowerCase())
                        //井号分隔符
                        .append(ActionEnum.POUND_SIGN.getName())
                        //试卷路径
                        .append(paper.getPath())
                        //竖线分隔符
                        .append(ActionEnum.VERTICAL_SIGN.getName());
            });
        } else if (OBTParamEnum.GET_PAPER_DATA_TYPE_MOCK.getParam().equals(dataType)) {
            //获取模拟试卷包，默认只获取第一个批次，第一个科目的试卷作为模拟测试卷
            PaperFileDTO mockPaper = iPaperService.getObtMockPaper(taskCode, CodeEnum.MOCK_PAPER.getCode());
            if (ObjectUtils.isEmpty(mockPaper)) {
                //未有模拟试卷包，获取失败
                log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "未有模拟试卷包，获取失败");
                throw new KqException(OBTResultEnum.GET_PAPER_DATA_WITHOUT.getResult(),
                        OBTResultEnum.GET_PAPER_DATA_WITHOUT.getRemark());
            }
            //组装模拟试卷信息返回数据
            result.append(OBTResultEnum.GET_PAPER_DATA_SUCCESS.getResult())
                    .append(ActionEnum.VERTICAL_SIGN.getName())
                    //模拟试卷MD5
                    .append(mockPaper.getMd5())
                    //井号分隔符
                    .append(ActionEnum.POUND_SIGN.getName())
                    //试卷路径
                    .append(mockPaper.getPath())
                    //竖线分隔符
                    .append(ActionEnum.VERTICAL_SIGN.getName());
        } else {
            //包类型不存在
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "包类型不存在");
            throw new KqException(OBTResultEnum.GET_PAPER_DATA_WITHOUT.getResult(),
                    OBTResultEnum.GET_PAPER_DATA_WITHOUT.getRemark());
        }
        //去除最后一个分隔符
        result.deleteCharAt(result.length() - 1);
        return result.toString();
    }

    @Override
    public String updatePaperDataState(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        //暂无试卷包下载管理表，直接返回成功状态
        return String.valueOf(OBTResultEnum.UPDATE_PAPER_DATA_STATE_SUCCESS.getResult());
    }

    @Override
    public String getPaperAuthorizationCode(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        //获取请求参数
        String type = request.getParameter(OBTParamEnum.GET_PAPER_AUTHORIZATION_CODE_TYPE.getParam());
        String timeCode = request.getParameter(OBTParamEnum.GET_PAPER_AUTHORIZATION_CODE_TIME_CODE.getParam());
        String roomCode = request.getParameter(OBTParamEnum.GET_PAPER_AUTHORIZATION_CODE_ROOM_CODE.getParam());
        String paperCode = request.getParameter(OBTParamEnum.GET_PAPER_AUTHORIZATION_CODE_PAPER_CODE.getParam());
        //解析试卷编号
        paperCode = paperCode.replaceAll("\\|",
                ActionEnum.COMMA_SIGN.getName());
        List<String> paperCodeList = Arrays.stream(paperCode.split(ActionEnum.COMMA_SIGN.getName()))
                .map(String::trim).collect(Collectors.toList());
        if (StringUtils.isEmpty(paperCode)) {
            //试卷编号不能为空
            log.error(request.getParameter(ActionEnum.ACTION.getName())
                    + ": {}", "试卷编号不能为空");
            throw new KqException(OBTResultEnum.GET_PAPER_AUTHORIZATION_CODE_WITHOUT.getResult(),
                    OBTResultEnum.GET_PAPER_AUTHORIZATION_CODE_WITHOUT.getRemark());
        }
        StringBuffer result = new StringBuffer();
        if (OBTParamEnum.GET_PAPER_AUTHORIZATION_CODE_TYPE_FORMAL.getParam().equals(type)) {
            //获取正式授权码包，获取批次试卷授权码信息
            List<PaperFileDTO> authorizationCodeList = iPaperService.getPaperAuthorizationCode(taskCode, roomCode, timeCode,
                    CodeEnum.FORMAL_PAPER.getCode(), paperCode);
            //校验试卷授权码是否存在
            if (CollectionUtils.isEmpty(authorizationCodeList)) {
                //未有试卷授权码，获取失败
                log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "未有试卷授权码，获取失败");
                throw new KqException(OBTResultEnum.GET_PAPER_AUTHORIZATION_CODE_WITHOUT.getResult(),
                        OBTResultEnum.GET_PAPER_AUTHORIZATION_CODE_WITHOUT.getRemark());
            }
            //组装返回结果数据
            result.append(OBTResultEnum.GET_PAPER_AUTHORIZATION_CODE_SUCCESS.getResult())
                    //竖线分隔符
                    .append(ActionEnum.VERTICAL_SIGN.getName());
            paperCodeList.forEach(code -> {
                //试卷编号，井号分隔符
                result.append(code).append(ActionEnum.POUND_SIGN.getName());
                Optional<PaperFileDTO> optional = authorizationCodeList.stream()
                        .filter(authorizationCode -> authorizationCode.getCode().equals(code))
                        .findFirst();
                if (optional.isPresent()) {
                    //存在试卷，返回路径
                    result.append(optional.get().getPath());
                } else {
                    //不存在试卷，返回指定数字
                    result.append(OBTResultEnum.GET_PAPER_AUTHORIZATION_CODE_PARTIAL_DELETED.getResult());
                }
                //竖线分隔符
                result.append(ActionEnum.VERTICAL_SIGN.getName());
            });
        } else if (OBTParamEnum.GET_PAPER_AUTHORIZATION_CODE_TYPE_MOCK.getParam().equals(type)) {
            //获取模拟授权码包
            if (paperCodeList.size() != 1) {
                log.error(request.getParameter(ActionEnum.ACTION.getName())
                        + ": {}", "获取授权码包时，试卷编号个数为 " + paperCodeList.size());
                throw new KqException(OBTResultEnum.GET_PAPER_AUTHORIZATION_CODE_WITHOUT.getResult(),
                        OBTResultEnum.GET_PAPER_AUTHORIZATION_CODE_WITHOUT.getRemark());
            }
            PaperFileDTO mockPaperAuthorizationCode = iPaperService
                    .getObtMockPaperAuthorizationCode(taskCode, paperCodeList.get(0), CodeEnum.MOCK_PAPER.getCode());
            if (ObjectUtils.isEmpty(mockPaperAuthorizationCode)) {
                //未有模拟授权码包，获取失败
                log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "未有模拟授权码包，获取失败");
                throw new KqException(OBTResultEnum.GET_PAPER_AUTHORIZATION_CODE_WITHOUT.getResult(),
                        OBTResultEnum.GET_PAPER_AUTHORIZATION_CODE_WITHOUT.getRemark());
            }
            //组装返回结果数据
            result.append(OBTResultEnum.GET_PAPER_AUTHORIZATION_CODE_SUCCESS.getResult())
                    //竖线分隔符
                    .append(ActionEnum.VERTICAL_SIGN.getName())
                    //模拟授权码试卷编号
                    .append(mockPaperAuthorizationCode.getCode())
                    //井号分隔符
                    .append(ActionEnum.POUND_SIGN.getName())
                    //文件路径
                    .append(mockPaperAuthorizationCode.getPath())
                    //竖线分隔符
                    .append(ActionEnum.VERTICAL_SIGN.getName());
        } else {
            //包类型不存在
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "包类型不存在");
            throw new KqException(OBTResultEnum.GET_PAPER_AUTHORIZATION_CODE_WITHOUT.getResult(),
                    OBTResultEnum.GET_PAPER_AUTHORIZATION_CODE_WITHOUT.getRemark());
        }
        //去除最后一个分隔符
        result.deleteCharAt(result.length() - 1);
        return result.toString();
    }

    @Override
    public String updatePaperAuthorizationCodeState(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        //暂无授权码下载管理表，直接返回成功状态
        return String.valueOf(OBTResultEnum.UPDATE_PAPER_AUTHORIZATION_CODE_STATE_SUCCESS.getResult());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String uploadTestReport(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        //获取请求参数
        String roomCode = request.getParameter(OBTParamEnum.UPLOAD_TEST_REPORT_ROOM_CODE.getParam());
        String reportXml = request.getParameter(OBTParamEnum.UPLOAD_TEST_REPORT_RESULT.getParam());
        //获取任务考点考场信息
        PlaceRoomInfoDTO placeRoomInfoDTO = iTaskPlaceService.getPlaceRoomInfoByCode(taskCode, roomCode);
        //校验任务考点考场信息
        if (ObjectUtils.isEmpty(placeRoomInfoDTO)) {
            //任务考点考场信息不存在
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "任务考点考场信息不存在");
            throw new KqException(OBTResultEnum.UPLOAD_TEST_REPORT_FAILED.getResult(),
                    OBTResultEnum.UPLOAD_TEST_REPORT_FAILED.getRemark());
        }
        //获取考场机位信息
        Integer seatNumber = iTaskRoomService.getSeatNumberByCode(taskCode, roomCode);
        if (ObjectUtils.isEmpty(seatNumber)) {
            //考场机位信息不存在
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "考场机位信息不存在");
            throw new KqException(OBTResultEnum.UPLOAD_TEST_REPORT_FAILED.getResult(),
                    OBTResultEnum.UPLOAD_TEST_REPORT_FAILED.getRemark());
        }
        //转换测试报告XML文本
        ObtTestReport obtTestReport = XmlUtil.toObject(reportXml, ObtTestReport.class);
        //设置测试报告数据
        TaskRoomTestReport taskRoomTestReport = new TaskRoomTestReport();
        //设置考点考场信息
        BeanUtils.copyProperties(placeRoomInfoDTO, taskRoomTestReport);
        //设置监考机信息
        ObtMonitorReport obtMonitorReport = obtTestReport.getObtMonitorReport();
        BeanUtils.copyProperties(obtMonitorReport, taskRoomTestReport);
        //判断监考机测试结果
        taskRoomTestReport.setMonitorPass(obtMonitorReport.getMonitorPass() == 1);
        //判断考生机测试结果
        ObtTestInfoReport obtTestInfoReport = obtTestReport.getObtTestInfoReport();
        Integer resultCount = Integer.valueOf(obtTestInfoReport.getResultCount());
        taskRoomTestReport.setClientPass(resultCount.compareTo(seatNumber) >= 0);
        //设置环境测试结果
        taskRoomTestReport.setClientTestNumber(Integer.valueOf(obtTestInfoReport.getClientCount()))
                .setClientPassNumber(resultCount);
        //保存考场测试报告
        this.saveTestReport(taskRoomTestReport, reportXml, request);
        return String.valueOf(OBTResultEnum.UPLOAD_TEST_REPORT_SUCCESS.getResult());
    }

    @Override
    public String examPackageSync(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        return null;
    }

    /**
     * 保存测试报告
     * @param taskRoomTestReport 测试报告
     * @param reportXml 测试报告详情XML
     * @param request 请求
     * @throws KqException 异常
     */
    private void saveTestReport(TaskRoomTestReport taskRoomTestReport,
                                String reportXml, HttpServletRequest request) {
        //获取考务中的测试报告
        TaskRoomTestReport testReport = iTaskRoomTestReportService
                .getByTaskRoom(taskRoomTestReport.getTaskId(), taskRoomTestReport.getRoomId());
        if (ObjectUtils.isEmpty(testReport)) {
            //不存在测试报告，插入测试报告
            if (!iTaskRoomTestReportService.save(taskRoomTestReport)) {
                //插入测试报告表失败
                log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "插入测试报告表失败");
                throw new KqException(OBTResultEnum.UPLOAD_TEST_REPORT_FAILED.getResult(),
                        OBTResultEnum.UPLOAD_TEST_REPORT_FAILED.getRemark());
            }
        } else {
            //存在测试报告，更新测试报告
            taskRoomTestReport.setId(testReport.getId());
            BeanUtils.copyProperties(taskRoomTestReport, testReport);
            iTaskRoomTestReportService.updateById(testReport);
        }
        //获取考务中的测试报告详情
        TaskRoomTestReportDetail taskRoomTestReportDetail = iTaskRoomTestReportDetailService
                .getByReportId(taskRoomTestReport.getId());
        if (ObjectUtils.isEmpty(taskRoomTestReportDetail)) {
            //不存在测试报告详情，插入测试报告详情
            TaskRoomTestReportDetail detail = new TaskRoomTestReportDetail();
            detail.setContent(reportXml)
                    .setTestReportId(taskRoomTestReport.getId());
            if (!iTaskRoomTestReportDetailService.save(detail)) {
                //插入测试报告详情表失败
                log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "插入测试报告详情表失败");
                throw new KqException(OBTResultEnum.UPLOAD_TEST_REPORT_FAILED.getResult(),
                        OBTResultEnum.UPLOAD_TEST_REPORT_FAILED.getRemark());
            }
            return;
        }
        //存在测试报告详情，更新测试报告详情
        taskRoomTestReportDetail.setContent(reportXml);
        iTaskRoomTestReportDetailService.updateById(taskRoomTestReportDetail);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String updateClosure(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        //获取请求参数
        String roomCodes = request.getParameter(OBTParamEnum.UPDATE_CLOSURE_ROOM_CODES.getParam());
        if (StringUtils.isEmpty(roomCodes)) {
            //考场编号为空
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "考场编号为空");
            throw new KqException(OBTResultEnum.UPDATE_CLOSURE_FAILED.getResult(),
                    OBTResultEnum.UPDATE_CLOSURE_FAILED.getRemark());
        }
        //获取考场编号
        String roomCode = Arrays.stream(roomCodes.split(","))
                .map(String::trim)
                //OBT会给到2个完全相同的并且用英文逗号分割的考场编号，只取第一个作为考场编号即可
                .findFirst()
                //取值失败
                .orElseThrow(() -> new KqException(OBTResultEnum.UPDATE_CLOSURE_FAILED.getResult(),
                        OBTResultEnum.UPDATE_CLOSURE_FAILED.getRemark()));
        //更新封场状态
        iTaskRoomService.updateClosureByCode(taskCode, roomCode);
        return String.valueOf(OBTResultEnum.UPDATE_CLOSURE_SUCCESS.getResult());
    }

    @Override
    public String getMonitorSettingBackupPath(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        return null;
    }

    @Override
    public String updateMonitorSettingBackupState(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        return null;
    }

    @Override
    public String getMonitorSettingBackup(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        return null;
    }

    @Override
    public String updateMonitorSettingBackupDownloadState(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        return null;
    }

    @Override
    public String getBasePackage(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        //获取基础包信息
        SysFile basePackage = iSysFileService.getBaseDataByTaskCode(taskCode);
        String basePackagePath = Optional.ofNullable(basePackage)
                .map(SysFile::getPath)
                //暂无基础包
                .orElseThrow(() -> new KqException(OBTResultEnum.GET_BASE_PACKAGE_OTHER.getResult(),
                        OBTResultEnum.GET_BASE_PACKAGE_OTHER.getRemark()));
        //拼接返回结果
        StringBuffer result = new StringBuffer();
        result.append(OBTResultEnum.GET_BASE_PACKAGE_CAN_DOWNLOAD.getResult())
                .append(ActionEnum.VERTICAL_SIGN.getName())
                .append(basePackagePath);
        return result.toString();
    }

    @Override
    public String updateBaseDataState(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        return null;
    }

    @Override
    public String getTaskCode(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        //获取考试任务名称
        Task task = iTaskService.getNameByCode(taskCode);
        if (ObjectUtils.isEmpty(task)) {
            //考试任务不存在
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "考试任务不存在");
            throw new KqException(OBTResultEnum.GET_TASK_CODE_FAILED.getResult(),
                    OBTResultEnum.GET_TASK_CODE_FAILED.getRemark());
        }
        //组装返回结果
        StringBuffer result = new StringBuffer();
        result.append(taskCode).append(ActionEnum.AND_SIGN.getName()).append(task.getName());
        return result.toString();
    }

    @Override
    public String getCandidateInfo(HttpServletRequest request, HttpServletResponse response, String taskCode) throws Exception {
        //获取请求参数
        String admissionNumber = request.getParameter(OBTParamEnum.GET_CANDIDATE_INFO_ADMISSION_NUMBER.getParam());
        String placeCode = request.getParameter(OBTParamEnum.GET_CANDIDATE_INFO_PLACE_CODE.getParam());
        String roomCode = request.getParameter(OBTParamEnum.GET_CANDIDATE_INFO_ROOM_CODE.getParam());
        String timeCode = request.getParameter(OBTParamEnum.GET_CANDIDATE_INFO_TIME_CODE.getParam());
        //返回结果
        CandidateInfoObtResult result = new CandidateInfoObtResult();
        //获取考生信息返回结果
        List<CandidateInfoObtResultDTO> candidateInfoObtResultDTOList = iCandidateService
                .getCandidateInfoObtResultDTO(PhotoTypeEnum.PERSONAL.getCode(), taskCode, admissionNumber);
        //校验考生是否存在
        if (CollectionUtils.isEmpty(candidateInfoObtResultDTOList)) {
            //未找到考生信息
            result.setFlag(OBTResultEnum.GET_CANDIDATE_INFO_NOT_FOUND.getResult());
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}",
                    OBTResultEnum.GET_CANDIDATE_INFO_NOT_FOUND.getRemark());
            throw new KqException(ResponseCode.EXAMINATION_EXAM_SYSTEM_BUSINESS_EXCEPTION.getCode(),
                    XmlUtil.toXml(result));
        }
        //校验当前考点编号（注意：不可能存在同一个考生不同批次考试在不同考点的情况）
        boolean placeMatch = candidateInfoObtResultDTOList.stream()
                .allMatch(info -> info.getPlaceCode().equals(placeCode));
        //校验在线添加的考生是否在当前考点
        if (!placeMatch) {
            //考生不是本考点考生，无法转移
            result.setFlag(OBTResultEnum.GET_CANDIDATE_INFO_NOT_CURRENT_PLACE.getResult());
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}",
                    OBTResultEnum.GET_CANDIDATE_INFO_NOT_CURRENT_PLACE.getRemark());
            throw new KqException(ResponseCode.EXAMINATION_EXAM_SYSTEM_BUSINESS_EXCEPTION.getCode(),
                    XmlUtil.toXml(result));
        }
        //获取当前批次考生信息（注意：同一个考生在同一个批次下只可能有一条编排数据）
        CandidateInfoObtResultDTO candidateInfoObtResultDTO = candidateInfoObtResultDTOList.stream()
                //校验是否有当前批次的考生信息
                .filter(info -> info.getTimeCode().equals(timeCode))
                .findFirst()
                //考生不是本批次考生，无法转移
                .orElseThrow(() -> new KqException(ResponseCode.EXAMINATION_EXAM_SYSTEM_BUSINESS_EXCEPTION.getCode(),
                        XmlUtil.toXml(result.setFlag(OBTResultEnum.GET_CANDIDATE_INFO_NOT_CURRENT_TIME.getResult()))));
        //校验考生是否为当前考场的考生
        if (candidateInfoObtResultDTO.getRoomCode().equals(roomCode)) {
            //本考场考生，无需转移
            result.setFlag(OBTResultEnum.GET_CANDIDATE_INFO_IS_CURRENT_ROOM.getResult());
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}",
                    OBTResultEnum.GET_CANDIDATE_INFO_IS_CURRENT_ROOM.getRemark());
            throw new KqException(ResponseCode.EXAMINATION_EXAM_SYSTEM_BUSINESS_EXCEPTION.getCode(),
                    XmlUtil.toXml(result));
        }
        BeanUtils.copyProperties(candidateInfoObtResultDTO, result);
        if (!StringUtils.isEmpty(result.getPhoto())) {
            //转换考生照片数据
            InputStream inputStream = HuaweiCloudObsUtil.getInputStream(result.getPhoto());
            String encoded = Base64.getEncoder().encodeToString(IOUtils.toByteArray(inputStream));
            inputStream.close();
            result.setPhoto(encoded);
        }
        result.setExamType(String.valueOf(OBTResultEnum.GET_CANDIDATE_INFO_EXAM_TYPE.getResult()))
                .setFlag(OBTResultEnum.GET_CANDIDATE_INFO_SUCCESS.getResult());
        return XmlUtil.toXml(result);
    }

    @Override
    public String getResultUploadPath(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        String path = configManager.getCloudRootPath();
        StringBuffer result = new StringBuffer();
        if (StringUtils.isEmpty(path)) {
            //考试结果上传路径不存在
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "考试结果上传路径不存在");
            throw new KqException(OBTResultEnum.GET_RESULT_UPLOAD_PATH_OTHER.getResult(),
                    OBTResultEnum.GET_RESULT_UPLOAD_PATH_OTHER.getRemark());
        }
        //组装返回结果
        result.append(OBTResultEnum.GET_RESULT_UPLOAD_PATH_SUCCESS.getResult())
                //竖线分隔符
                .append(ActionEnum.VERTICAL_SIGN.getName())
                //根路径
                .append(path)
                //考试任务编号
                .append(taskCode)
                //斜杠
                .append(ActionEnum.SLASH_SIGN.getName())
                //考试结果目录名
                .append(configManager.getResultPath())
                //斜杠
                .append(ActionEnum.SLASH_SIGN.getName());
        return result.toString();
    }

    @Override
    public String verifyResult(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String updateResultState(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        //获取时间戳
        long timestamp = System.currentTimeMillis();
        //获取请求参数
        String timeRoomCode = request.getParameter(OBTParamEnum.UPDATE_RESULT_STATE_TIME_ROOM_CODE.getParam());
        String objectUrls = request.getParameter(OBTParamEnum.UPDATE_RESULT_STATE_OBJECT_URL.getParam());
        //获取任务批次、考场信息
        TimeRoom timeRoom = iTimeRoomService.getByTaskTimeRoomCode(taskCode, timeRoomCode);
        if (ObjectUtils.isEmpty(timeRoom)) {
            //场次信息不存在
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "场次信息不存在");
            throw new KqException(OBTResultEnum.UPDATE_RESULT_STATE_FAILED.getResult(),
                    OBTResultEnum.UPDATE_RESULT_STATE_FAILED.getRemark());
        }
        //解析考试结果路径数据
        if (StringUtils.isEmpty(objectUrls)) {
            //对象存储路径为空
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "对象存储路径为空");
            throw new KqException(OBTResultEnum.UPDATE_RESULT_STATE_FAILED.getResult(),
                    OBTResultEnum.UPDATE_RESULT_STATE_FAILED.getRemark());
        }
        //分割对象存储路径
        List<String> objectUrlList = Arrays.stream(objectUrls.split("\\|"))
                .map(String::trim)
                .collect(Collectors.toList());
        List<ExamResultMonitor> examResultMonitorList = objectUrlList.stream().map(url -> {
            ExamResultMonitor examResultMonitor = new ExamResultMonitor();
            examResultMonitor.setTaskId(timeRoom.getTaskId())
                    .setTimeId(timeRoom.getTimeId())
                    .setRoomId(timeRoom.getRoomId())
                    //OBT考试系统只有正式考试会上传考试结果
                    .setExamType(Integer.valueOf(OBTParamEnum.UPDATE_RESULT_STATE_TYPE_FORMAL.getParam()))
                    .setPackageType(url.substring(url.lastIndexOf('.') + 1))
                    .setPackageName(url.substring(url.lastIndexOf("/") + 1))
                    .setPath(url)
                    .setSize(HuaweiCloudObsUtil.getObjectMetadata(url).getContentLength())
                    .setTimestamp(timestamp)
                    .setSuccess(true);
            return examResultMonitor;
        }).collect(Collectors.toList());
        //插入考试结果表
        if (!iExamResultMonitorService.saveBatch(examResultMonitorList)) {
            //插入考试结果表失败
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "插入考试结果表失败");
            throw new KqException(OBTResultEnum.UPDATE_RESULT_STATE_FAILED.getResult(),
                    OBTResultEnum.UPDATE_RESULT_STATE_FAILED.getRemark());
        }
        return String.valueOf(OBTResultEnum.UPDATE_RESULT_STATE_SUCCESS.getResult());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String updateExamMonitor(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        //获取请求参数
        String stateType = request.getParameter(OBTParamEnum.UPDATE_EXAM_MONITOR_STATE_TYPE.getParam());
        String roomCode = request.getParameter(OBTParamEnum.UPDATE_EXAM_MONITOR_ROOM_CODE.getParam());
        String timeCode = request.getParameter(OBTParamEnum.UPDATE_EXAM_MONITOR_TIME_CODE.getParam());
        //获取考试过程监控信息
        ExamMonitor examMonitor = iExamMonitorService.getByTimeAndRoomCode(taskCode, roomCode, timeCode);
        //校验考试过程监控信息
        if (ObjectUtils.isEmpty(examMonitor)) {
            //考试过程监控信息不存在
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "考试过程监控信息不存在");
            throw new KqException(OBTResultEnum.UPDATE_EXAM_MONITOR_FAILED.getResult(),
                    OBTResultEnum.UPDATE_EXAM_MONITOR_FAILED.getRemark());
        }
        switch (OBTStateTypeEnum.getByType(stateType)) {
            //下载考务包
            case ROOM_PACKAGE:
                examMonitor.setDownloadRoomData(true);
                break;
            //下载试卷
            case PAPER:
                examMonitor.setDownloadPaper(true);
                break;
            //下载授权码
            case AUTHORIZATION_CODE:
                examMonitor.setDownloadDecode(true);
                break;
            //考试开始
            case STARTED:
                examMonitor.setExamStarted(true);
                break;
            //考试结束
            case ENDED:
                examMonitor.setExamEnded(true);
                break;
            //考试完成
            case FINISHED:
                examMonitor.setFinish(true);
                break;
            //上传考试结果
            case UPLOADED:
                examMonitor.setUploadResult(true);
                break;
            //导出考试结果
            case EXPORTED:
                examMonitor.setExport(true);
                break;
            default:
                break;
        }
        //更新考试过程监控信息
        iExamMonitorService.updateById(examMonitor);
        return String.valueOf(OBTResultEnum.UPDATE_EXAM_MONITOR_SUCCESS.getResult());
    }

    @Override
    public String getTimeByPlace(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        //获取请求参数
        String placeCode = request.getParameter(OBTParamEnum.GET_TIME_BY_PLACE_PLACE_CODE.getParam());
        //返回结果
        PlaceTimeResult placeTimeResult = new PlaceTimeResult();
        //获取批次信息
        List<TimeInfoResultDTO> timeInfoResultList = iTimeService.getTimeInfoResult(taskCode, placeCode);
        //获取场次信息
        List<TimeRoomInfoResultDTO> timeRoomInfoResultList = iTimeRoomService.getTimeRoomInfoResultDTO(taskCode, placeCode);
        //获取考场信息
        List<RoomInfoResult> roomInfoResultList = iTaskRoomService.getRoomInfoResult(taskCode, placeCode);
        //组装数据
        this.convertPlaceTimeResult(timeInfoResultList, timeRoomInfoResultList,
                roomInfoResultList, placeTimeResult, request);
        return JSONObject.toJSONString(placeTimeResult, SerializerFeature.PrettyFormat,
                SerializerFeature.WriteMapNullValue);
    }

    @Override
    public String getTestInventory(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        return null;
    }

    @Override
    public String updateTestInventoryState(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        return null;
    }

    /**
     * 组装考点批次信息数据
     * @param timeInfoResultList 批次信息
     * @param timeRoomInfoResultList 场次信息
     * @param roomInfoResultList 考场信息
     * @param placeTimeResult 返回结果
     * @param request 请求
     */
    private void convertPlaceTimeResult(List<TimeInfoResultDTO> timeInfoResultList,
                                        List<TimeRoomInfoResultDTO> timeRoomInfoResultList,
                                        List<RoomInfoResult> roomInfoResultList,
                                        PlaceTimeResult placeTimeResult,
                                        HttpServletRequest request) {
        if (CollectionUtils.isEmpty(timeInfoResultList) ||
                CollectionUtils.isEmpty(timeRoomInfoResultList) ||
                CollectionUtils.isEmpty(roomInfoResultList)) {
            //考点批次信息数据为空
            log.error(request.getParameter(ActionEnum.ACTION.getName()) + ": {}", "考点批次信息数据为空");
            placeTimeResult.setError(OBTResultEnum.GET_TIME_BY_PLACE_FAILED_TO_GOT.getRemark())
                    .setCode(String.valueOf(OBTResultEnum.GET_TIME_BY_PLACE_FAILED_TO_GOT.getResult()));
            throw new KqException(ResponseCode.EXAMINATION_EXAM_SYSTEM_BUSINESS_EXCEPTION.getCode(),
                    JSONObject.toJSONString(placeTimeResult, SerializerFeature.PrettyFormat,
                            SerializerFeature.WriteMapNullValue));
        }
        //组装批次信息返回结果
        List<TimeInfoResult> timeInfoResultDTOList = timeInfoResultList.stream()
                .map(timeInfo -> this.convertTimeInfoResult(timeInfo, timeRoomInfoResultList))
                .collect(Collectors.toList());
        placeTimeResult.setBatchList(timeInfoResultDTOList)
                .setRoomList(roomInfoResultList);
    }

    /**
     * 组装批次信息返回结果
     * @param timeInfoResultDTO 批次信息DTO
     * @param timeRoomInfoResultList 场次信息返回结果DTO
     * @return 批次信息返回结果
     */
    private TimeInfoResult convertTimeInfoResult(TimeInfoResultDTO timeInfoResultDTO, List<TimeRoomInfoResultDTO> timeRoomInfoResultList) {
        TimeInfoResult timeInfoResult = new TimeInfoResult();
        //组装科目编号
        String codes = timeInfoResultDTO.getSubjectList()
                .stream()
                .map(Subject::getCode)
                .collect(Collectors.joining(","));
        //组装科目名称
        String names = timeInfoResultDTO.getSubjectList()
                .stream()
                .map(Subject::getName)
                .collect(Collectors.joining(","));
        //计算考试时间
        Duration duration = Duration.between(timeInfoResultDTO.getStartTime(), timeInfoResultDTO.getEndTime());
        int examTime = (int) duration.toMinutes();
        //组装考场信息
        List<String> roomInfoList = new ArrayList<>();
        for (TimeRoomInfoResultDTO timeRoomInfo : timeRoomInfoResultList) {
            if (timeInfoResultDTO.getCode().equals(timeRoomInfo.getTimeCode())) {
                //拼接场次信息字符串
                StringBuffer roomInfo = new StringBuffer();
                //考场编号
                roomInfo.append(timeRoomInfo.getRoomCode()).append(ActionEnum.COLON_SIGN.getName())
                        //考生人数
                        .append(timeRoomInfo.getCount()).append(ActionEnum.COLON_SIGN.getName())
                        //场次编号
                        .append(timeRoomInfo.getTimeRoomCode());
                roomInfoList.add(roomInfo.toString());
            }
        }
        String roomInfo = String.join(",", roomInfoList);
        //设置值
        timeInfoResult.setBatchNum(timeInfoResultDTO.getCode())
                .setBatchName(timeInfoResultDTO.getName())
                .setBatchType(OBTResultEnum.GET_TIME_BY_PLACE_TIME_TYPE_FORMAL.getResult())
                .setSubjectId(codes)
                .setSubjectName(names)
                .setStartTime(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss")
                        .format(timeInfoResultDTO.getStartTime()))
                .setHowLong(examTime)
                .setRoomInfo(roomInfo);
        return timeInfoResult;
    }

    @Override
    public String getHuaweiCloudObsInfo(){
        //获取华为云OBS配置信息
        HuaweiCloudObsInfo obsInfo = new HuaweiCloudObsInfo();
        BeanUtils.copyProperties(huaweiCloudObsConfig, obsInfo);
        String json = JSONObject.toJSONString(obsInfo, SerializerFeature.PrettyFormat,
                SerializerFeature.WriteMapNullValue);
        //加密并返回结果
        return SecModuleUtil.encrypString(json);
    }

    @Override
    public String getOumaExaminationConfig(OumaParam oumaParam) {
        OumaExaminationConfig config = new OumaExaminationConfig();
        config.setOpen("N")
                .setApiKey(obtConfig.getApiKey())
                .setApiSecret(obtConfig.getApiSecret());
        return JSONObject.toJSONString(config, SerializerFeature.PrettyFormat);
    }

    @Override
    public String upload(long timestamp, HttpServletRequest request, HttpServletResponse response,
                         MultipartFile file, String taskCode, String type, String roomCode) {
        return null;
    }

    @Override
    public String postBehaviorAnalysis(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        return null;
    }

    @Override
    public String updateBackUpState(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        return null;
    }

    @Override
    public String newRegisterRoom(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        //GCE注册接口，暂不适用于OBT
        return null;
    }

    @Override
    public String getResitRoomPackage(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        return null;
    }

    @Override
    public String updateResitRoomPackageState(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        return null;
    }

    @Override
    public String checkExamSystemConnection(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        return null;
    }

    @Override
    public String getServerTime(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        return null;
    }

}
